﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Brainee.Search;

namespace Brainee.Optimization
{
  public class SimulatedAnnealingAlgorithm : IOptimizationAlgorithm
  {
    public Func<UInt32, double> Schedule;

    public OptimizationSolution Solve (IOptimizationProblem problem)
    {
      if (problem == null)
        throw new ArgumentNullException ("problem");

      OptimizationState current = new OptimizationState (problem.InitialState, problem.Evaluate (problem.InitialState));
      UInt32 steps = 0;
      while (true)
      {
        double temperature = Schedule (steps);
        steps++;

        if (temperature == 0)
          break;

        IState successor = problem.RandomSuccessor (current.State);
        OptimizationState neighbor = new OptimizationState (successor, problem.Evaluate(successor));

        if (neighbor.Value < current.Value)
        {
          if (new Random ().NextDouble () > Math.Exp ((neighbor.Value - current.Value) / temperature))
            continue;
        }

        current = neighbor;
      }

      return new OptimizationSolution (current, steps);
    }
  }
}
